package ps.server.net;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;

import ps.net.Packet;
import ps.server.ServerPacketHandler;
import ps.server.rights.User;



public class ClientInfo extends Thread {
    
    Socket socket;
    ServerPacketHandler serverPacketHandler;
    
    InputStream in;
    OutputStream out;
    
    boolean running = true;
    
    boolean logedIn = false;
    long lastRecievedMsgTime = 0;
    long lastClientInfoSent = 0;
    int ping = 0;
    
    boolean afk = false;
    boolean logReadActive = false;
    boolean linkDead = false;
    boolean dpsParseSharer = false;
    int groupNumber = 0;
    
    User user;
    
    public ClientInfo() {
    }
    
    public ClientInfo(Socket socket, ServerPacketHandler serverPacketHandler) {
        super("ClientInfo " + socket.getInetAddress());
        this.socket = socket;
        this.serverPacketHandler = serverPacketHandler;
    }
    
    public void open() throws IOException {
        this.in = socket.getInputStream();
        this.out = socket.getOutputStream();
        start();
    }
    
    public void close() {
        running = false;
        try {
            if (in != null) {
                in.close();
            }
            if (out != null) {
                out.close();
            }
            if (socket != null) {
                socket.close();
                System.out.println("SOCKET CLOSED FROM: " + (user != null ? user.getName() : "<unknown>"));
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        in = null;
        out = null;
        socket = null;
    }
    
    synchronized void send(ByteArrayOutputStream buffer) {
        if (running) {
            try {

                buffer.writeTo(out);
                out.flush();
                
            } catch (SocketException ex) {
                if (running) {
                    serverPacketHandler.fireClientConectionLost(this);
                }
            } catch (IOException ex) {
                if (running) {
                    ex.printStackTrace();
                    serverPacketHandler.fireClientConectionLost(this);
                }
            }
        }
    }
    
    @Override
    public void run() {
        while (running) {
            try {
                Packet packet = new Packet(this);
                packet.readPacket(in);
                if (packet.getType() >= 0) {
                    packet.setTime(System.currentTimeMillis());
//                    System.out.println("RECIEVED: " + packet);
                    setLastRecievedMsgTime(System.currentTimeMillis());
                    serverPacketHandler.addRecievedPacket(packet);
                    if (packet.isTypeOf(Packet.TYPE_LOGOUT)) {
                        running = false;
                    }
                } else {
                    serverPacketHandler.fireClientConectionLost(this);
                }
            } catch (SocketException ex) {
                if (running) {
                    serverPacketHandler.fireClientConectionLost(this);
                }
            } catch (SocketTimeoutException ex) {
                if (running) {
                    serverPacketHandler.fireClientConectionLost(this);
                }
            } catch (Exception ex) {
                if (running) {
                    ex.printStackTrace();
                    serverPacketHandler.fireClientConectionLost(this);
                }
            }
        }
    }
    
    public long getLastRecievedMsgTime() {
        return lastRecievedMsgTime;
    }
    
    public void setLastRecievedMsgTime(long lastRecievedMsgTime) {
        this.lastRecievedMsgTime = lastRecievedMsgTime;
    }
    
    public void setUser(User user) {
        this.user = user;
    }
    
    public User getUser() {
        return user;
    }

    public int getPing() {
        return ping;
    }
    
    public void setPing(int ping) {
        this.ping = ping;
    }

    public boolean isAfk() {
        return afk;
    }
    
    public void setAfk(boolean afk) {
        this.afk = afk;
    }
    
    public boolean isLogReadActive() {
        return logReadActive;
    }
    
    public void setLogReadActive(boolean logReadActive) {
        this.logReadActive = logReadActive;
    }

    public boolean isLinkDead() {
        return linkDead;
    }
    
    public void setLinkDead(boolean linkDead) {
        this.linkDead = linkDead;
    }

    public boolean isLogedIn() {
        return logedIn;
    }

    public void setLogedIn(boolean logedIn) {
        this.logedIn = logedIn;
    }
    
    public long getLastClientInfoSent() {
        return lastClientInfoSent;
    }
    
    public void setLastClientInfoSent(long lastClientInfoSent) {
        this.lastClientInfoSent = lastClientInfoSent;
    }
    
    public boolean isDpsParseSharer() {
        return dpsParseSharer;
    }
    
    public void setDpsParseSharer(boolean dpsParseSharer) {
        this.dpsParseSharer = dpsParseSharer;
    }
    
    public int getGroupNumber() {
        return groupNumber;
    }
    
    public void setGroupNumber(int groupNumber) {
        this.groupNumber = groupNumber;
    }
    
}
